#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""时间日期相关操作类。

时间日期格式处理/每月第一天/每周第一天/是否为国内节假日/等操作。

Attributes:
    __version__ (str): "0.0.1"
    __copyright__ (str): "Copyright (C) 2025 z"
    __license__ (str): "MIT"
    __author__ (str): "Z"
"""

import time
import datetime
from dateutil import parser
from dateutil.tz import tzlocal

from wingman import logger
from wingman.common.error import ErrorCode


class CustomEpoch:
    """时间日期相关操作类。

    时间日期格式处理/每月第一天/每周第一天/是否为国内节假日/等操作。
    """

    def __init__(self):
        self.today = datetime.date.today()      # class
        self.now_time_unix = time.time()         # 当前时间 1741747852.5805547
        self.now_time_struct = time.localtime()        # 当前时间 time.struct_time(tm_year=2025, tm_mon=3, tm_mday=12, tm_hour=9, tm_min=53, tm_sec=49, tm_wday=2, tm_yday=71, tm_isdst=0)
        self.now_time = time.asctime(time.localtime(time.time()))   # Wed Mar 12 09:53:49 2025
        # # 当前时间格式化
        # curtime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        # print(curtime)
        # # 当前时间格式化
        # curtime = time.strftime("%Y-%m-%d", time.localtime())
        # print(curtime)
        # # 也可以使用asctime()进行时间格式化
        # print(time.asctime(localtime))

    # TODO
    def is_legal_holiday(self):
        """创建一个国家或地区对应的HolidayCalendar对象"""
        return False

    def get_today(self):
        # today = datetime.date.today()
        # result = today.strftime('%Y-%m-%d')
        return self.today.strftime('%Y-%m-%d')  # 直接返回格式化后的日期字符串

    def get_week(self):
        """今天是星期几"""
        # 现在是周几，英文
        print(time.strftime("%a", self.now_time_struct))
        print(time.strftime("%A", self.now_time_struct))
        # 现在是周几，数字
        print(time.strftime("%w", self.now_time_struct))
        # 0是周日 ###返回从0开始的数字，比如今天是星期5，那么返回的就是4
        print(datetime.datetime.now().weekday())
        # 返回数字1-7代表周一到周日
        print(datetime.datetime.now().isoweekday())
        return None

    def is_monday(self):
        """判断是否是每周一"""
        if self.today.weekday() == 0:
            return True
        else:
            return False

    def is_month_first_day(self):
        """判断是否是每月一号"""
        if self.today.day == 1:
            return True
        else:
            return False

    def get_last_month_start_end(self):
        """
        获取上月第一天和最后一天并返回(元组)
        :return:
        example:
            now date:2020-03-06
            return:2020-02-01,2020-02-29
        """
        last_month_last_day = datetime.date(self.today.year, self.today.month, 1) - datetime.timedelta(1)
        last_month_first_day = datetime.date(last_month_last_day.year, last_month_last_day.month, 1)
        return last_month_first_day, last_month_last_day

    def get_yesterday(self):
        """获取昨天的日期
        example:
        2025-03-11
        """
        yesterday=self.today-datetime.timedelta(days=1)
        return yesterday

    def get_unix_time(self, unix_time):
        """时间戳转日期时间格式字符串：

        时间戳 -> 日期时间格式字符串

        :param unix: 时间戳; int -> 1632196800
        :return: 日期时间格式字符串; str -> "%Y-%m-%d %H:%M:%S"
        """
        # 使用time
        date_array = time.localtime(unix_time)
        date_time = time.strftime("%Y-%m-%d %H:%M:%S", date_array)

        # 使用datetime
        date_array = datetime.datetime.fromtimestamp(unix_time)
        date_time = date_array.strftime("%Y-%m-%d %H:%M:%S")

        return date_time

    def get_time_unix(self, date_time):
        """日期时间格式字符串转时间戳：

        日期时间格式字符串 -> 时间戳

        :param stringTime: 日期时间格式字符串; str -> "%Y-%m-%d %H:%M:%S"
        :return: 时间戳; float -> 1632196800.0
        """
        date_array = time.strptime(date_time, "%Y-%m-%d %H:%M:%S")

        return time.mktime(date_array)

    def get_cert_expire(self, date_time):
        """计算当前时间到指定时间的剩余天数
        :param date_time: 目标时间字符串，格式如"Aug  9 01:41:01 2025 GMT"
        :return: 剩余天数（整数）
        """
        # 将输入时间字符串转换为时间戳
        target_time = time.strptime(date_time, "%b %d %H:%M:%S %Y %Z")
        target_timestamp = time.mktime(target_time)
        # 获取当前时间戳
        current_timestamp = time.time()
        # 计算时间差（秒），并转换为天数
        time_diff = target_timestamp - current_timestamp
        days_diff = int(time_diff // (24 * 60 * 60))
        return days_diff

    def get_domain_expire(self, date_time):
        """计算当前时间到指定时间的剩余天数
        :param date_time: 目标时间字符串，格式如"2034-10-20T19:56:17Z"
        :return: 剩余天数（整数）
        """
        # 将输入时间字符串转换为时间戳
        target_time = time.strptime(date_time, "%Y-%m-%dT%H:%M:%SZ")
        target_timestamp = time.mktime(target_time)
        # 获取当前时间戳
        current_timestamp = time.time()
        # 计算时间差（秒），并转换为天数
        time_diff = target_timestamp - current_timestamp
        days_diff = int(time_diff // (24 * 60 * 60))
        return days_diff

    def get_expire_date(self, date_time):
        """计算当前时间到指定时间的剩余天数
        :param date_time: 目标时间字符串，格式如"2034-10-20T19:56:17Z"
        :return: 剩余天数（整数）%a %b %d %H:%M:%S %Y   datetime.datetime(2031, 1, 8, 17, 59, 51)
        """
        DATETIME_FORMAT = '%Y %m %b %H %M %S'
        # logger.error(ErrorCode.SUCCESS.value, date_time, __name__)
        content = datetime.datetime.strptime(
            parser.parse(date_time).astimezone(tzlocal()).strftime(DATETIME_FORMAT),
            DATETIME_FORMAT
        )
        # logger.error(ErrorCode.SUCCESS.value, content, __name__)
        # 将datetime对象转换为字符串
        content_str = content.strftime("%Y-%m-%d %H:%M:%S")
        # 将输入时间字符串转换为时间戳
        target_time = time.strptime(content_str, "%Y-%m-%d %H:%M:%S")
        # logger.error(ErrorCode.SUCCESS.value, target_time, __name__)
        target_timestamp = time.mktime(target_time)
        # logger.error(ErrorCode.SUCCESS.value, target_timestamp, __name__)
        # 计算时间差（秒），并转换为天数
        time_diff = target_timestamp - self.now_time_unix
        days_diff = int(time_diff // (24 * 60 * 60))
        # logger.error(ErrorCode.SUCCESS.value, days_diff, __name__)
        return days_diff


if __name__ == "__main__":
    ctime = CustomEpoch()
    print(ctime.is_legal_holiday())
    # print(ctime.get_expire_date("2034-10-20T19:56:17Z"))
    # print(ctime.get_week())
    # print(ctime.is_Monday())
    # print(ctime.is_month_first_day())
    # print(ctime.get_last_month_start_end())
    # print(ctime.get_yesterday())
    # print(ctime.get_unix_time(1632196800.0))
    # print(ctime.get_time_unix("2020-03-06 23:23:23"))


# # 判断节点的第一个工作日是哪天 
# import datetime
# import holidays
# # 获取当前日期
# today = datetime.date.today()
# # 获取法定节日列表
# cn_holidays = holidays.China()
# # 判断某周的第一天和某月的第一天是否是法定节日
# if today.weekday() == 0 and today.day == 1 and (today.month, today.day) in cn_holidays:
#     # 找到下一个工作日
#     next_workday = today + datetime.timedelta(1)
#     while next_workday.weekday() >= 5 or (next_workday.month, next_workday.day) in cn_holidays:
#         next_workday += datetime.timedelta(1)
#     # 输出结果
#     print("下一个工作日是:", next_workday)
# else:
#     print("不是法定节日的每周一或每月第一天")


# 模块	说明
# time	time是一个仅包含与日期和时间相关的函数和常量的模块，在本模块中定义了C/C++编写的几个类。例如，struct_time类
# datetime	datetime是一个使用面向对象编程设计的模块，可以在Python中使用日期和时间。它定义了几个表示日期和时间的类
# calendar	日历是一个提供函数的模块，以及与Calendar相关的几个类，它们支持将日历映像生成为text，html，….
# locale	该模块包含用于格式化或基于区域设置分析日期和时间的函数。
#         UTC（CoordinatedUniversal Time，世界协调时）亦即格林威治天文时间，世界标准时间。在中国为UTC+8。
#         DST（DaylightSaving Time）即夏令时。是一种为节约能源而人为规定地方时间的制度，一般在天亮早的夏季人为将时间提前一小时

#  时间元组
# Python时间函数将时间处理为9个数字的元组，各个索引所代表的字段及取值范围如下所示：

# 索引	字段	值
# 0	4位数，表示年份	2018，2019…
# 1	月份	1 ~ 12
# 2	日期	1 ~ 31
# 3	小时	0 ~ 23
# 4	分钟	0 ~ 59
# 5	秒	0 ~ 61(60或61是闰秒)
# 6	星期几	0 ~ 6(0是星期一)
# 7	一年的第几天	1 ~ 366(朱利安日)
# 8	夏令时	1，0，1，-1是决定是否为夏令时的旗帜

#  1 year (four digits, e.g. 2018)
#  2 month (1-12)
#  3 day (1-31)
#  4 hours (0-23)
#  5 minutes (0-59)
#  6 seconds (0-59)
#  7 weekday (0-6, Monday is 0)
#  8 Julian day (day in the year, 1-366)
#  9 #夏令时格式，0：正常格式，1：夏令时格式，-1：根据当前的日期时间格式来判定
# 10 DST (Daylight Savings Time) flag (-1, 0 or 1)

# 上面的元组相当于struct_time结构。此结构具有以下属性：

# 索引	字段	值
# 0	tm_year	2018，2019…
# 1	tm_mon　	1 ~ 12
# 2	tm_mday	1 ~ 31
# 3	tm_hour	0 ~ 23
# 4	tm_min	0 ~ 59
# 5	tm_sec	0 ~ 61(60或61是闰秒)
# 6	tm_wday	0 ~ 6(0是星期一)
# 7	tm_yday	1 ~ 366(朱利安日)
# 8	tm_isdst	1，0，1，-1是决定是否为夏令时的旗帜

# time模块
# time模块，它提供了处理时间和表示之间转换的功能。help(time)之后可以知道time有2种时间表示形式：
# 1、时间戳表示法，即以整型或浮点型表示的是一个以秒为单位的时间间隔。这个时间的基础值是从1970年的1月1号零点开始算起。
# 2、元组格式表示法，这个元组有9个整型内容。分别表示不同的时间含义。

# 编号	方法	描述
# 1	time.time()	返回当前时间时刻，浮点数形式秒数，不支持参数
# 2	time.clock()	返回当前程序的cpu执行时间。为了测量不同方法的计算成本，time.clock的值比time.time()的值更有用。unix系统始终返回全部运行时间；而windows从第二次开始都是以第一次调用此函数时的时间戳作为基准
# 3	time.sleep(secs)	暂停调用线程secs秒，接受整型和浮点型参数。
# 4	time.gmtime([secs])	将时间戳转换为UTC时间元组格式。接受一个浮点型时间戳参数，其默认值为当前时间戳。
# 5	time.localtime([secs])	将时间戳转换为本地时间元组格式。接受一个浮点型时间戳参数，其默认值为当前时间戳。
# 6	time.asctime([tupletime])	接受时间元组，并返回一个可读的24个字符的字符串，例如’Tue Dec 11 22:07:14 2019’，默认值为localtime()返回值。
# 7	time.ctime([secs])	接受时间戳，转换为字符串。其默认值为当前时间戳。函数等价于asctime(localtime(seconds))。
# 8	time.mktime(tupletime)	将本地时间元组，转换为时间戳（浮点值，该时间点以秒为单位表示。）。接受一个时间元组，必选。
# 9	time.strftime(fmt[,tupletime])	将时间元组以指定的格式（字符串fmt指定）转换为字符串形式。接受字符串格式化串、时间元组。时间元组为可选，默认为localtime()
# 10	time.strptime(str,fmt="")	
# 根据格式字符串fmt解析str，并返回元组格式的时间。

# strftime()的逆向过程。接受字符串，时间格式2个参数，都是必选

# 11	time.altzone	本地DST时区的偏移量(以秒为单位的UTC)。
# 12	time.tzset()	改变本地时区

# 时间字符串支持的格式符号：

#  1 格式  含义  备注
#  2 %a  本地（locale）简化星期名称
#  3 %A  本地完整星期名称
#  4 %b  本地简化月份名称
#  5 %B  本地完整月份名称
#  6 %c  本地相应的日期和时间表示
#  7 %d  一个月中的第几天（01 - 31）
#  8 %H  一天中的第几个小时（24小时制，00 - 23）
#  9 %I  第几个小时（12小时制，01 - 12）
# 10 %j  一年中的第几天（001 - 366）
# 11 %m  月份（01 - 12）
# 12 %M  分钟数（00 - 59）
# 13 %p  本地am或者pm的相应符
# 14 %S  秒（01 - 61）
# 15 %U  一年中的星期数。（00 - 53星期天是一个星期的开始。）第一个星期天之前的所有天数都放在第0周。
# 16 %w  一个星期中的第几天（0 - 6，0是星期天）
# 17 %W  和%U基本相同，不同的是%W以星期一为一个星期的开始。
# 18 %x  本地相应日期
# 19 %X  本地相应时间
# 20 %y  去掉世纪的年份（00 – 99）
# 21 %Y  完整的年份
# 22 %Z  时区的名字（如果不存在为空字符）
# 23 %%  ‘%’字符

# 注意：
# 1、“%p”只有与“%I”配合使用才有效果。
# 2、文档中强调确实是0-61，而不是59，闰年秒占两秒
# 3、当使用strptime()函数时，只有当在这年中的周数和天数被确定的时候%和%W才会被计算

# time模块重要属性

# 序号	属性	说明
# 1	time.timezone	UTC和本地时区(不含DST)之间的偏移量，以秒计
# 2	time.tzname	关于(标准时区名称, 夏令时时区名称)的元组
# 3	time.altzone	当地夏令时时间与标准UTC时间的误差，以秒计
# 4	time.daylight	当地时间是否反映夏令时，默认为0
